package com.ltsznh.android.anti_villain;

import android.content.Context;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.Environment;
import android.util.Log;
import android.widget.Toast;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;

/**
 * Created by 涛 on 2014/7/21.
 */
public class ARecorder {
    private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss");
    private static int frequency = 44100;//采样频率
    private int bufferSizeBytes = 0;//缓冲区字节大小

    private AudioRecord audioRecord;
    public boolean isRecording = false;

    private String audioFile = "";
    private String waveFile = "";

    public ARecorder(Context context,String type, String num, String IO,int source) {
        String status = Environment.getExternalStorageState();
        String path;
        if(status.equals(Environment.MEDIA_MOUNTED)){
            path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/.Anti-Villain/" + type + "/" + num;
            File file = new File(path);
            if(!file.exists()){
                file.mkdirs();
            }
        }else {
            Toast.makeText(context,"无SD卡，无法录音",Toast.LENGTH_SHORT).show();
            return;
        }
        audioFile = path + "/record.raw";
        waveFile = path +  "/" + IO + simpleDateFormat.format(System.currentTimeMillis()) + "_" + (int) ((Math.abs(Math.random() - 0.1) + 0.1) * 1000) + ".wav";
        int channelConfiguration = AudioFormat.CHANNEL_IN_STEREO;//声道
        int audioFormat = AudioFormat.ENCODING_PCM_16BIT;//音频数据格式
        int audioSource = source;//音源
        bufferSizeBytes = AudioRecord.getMinBufferSize(frequency,channelConfiguration,audioFormat);
        //初始化麦克
        audioRecord = new AudioRecord(audioSource,frequency,channelConfiguration,audioFormat,bufferSizeBytes);
        if(audioRecord.getState() == AudioRecord.STATE_UNINITIALIZED){//摄像头旁
            audioRecord = new AudioRecord(MediaRecorder.AudioSource.CAMCORDER,frequency,channelConfiguration,audioFormat,bufferSizeBytes);
        }
        if(audioRecord.getState() == AudioRecord.STATE_UNINITIALIZED){//麦克
            audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,frequency,channelConfiguration,audioFormat,bufferSizeBytes);
        }
        if(audioRecord.getState() == AudioRecord.STATE_UNINITIALIZED){//默认
            audioRecord = new AudioRecord(MediaRecorder.AudioSource.DEFAULT,frequency,channelConfiguration,audioFormat,bufferSizeBytes);
        }

        if(audioRecord.getState() == AudioRecord.STATE_INITIALIZED){
            audioRecord.startRecording();
            isRecording = true;
            new Thread(new AudioRecordThread()).start();
        }else {
            Toast.makeText(context, "麦克存在问题，无法录音", Toast.LENGTH_SHORT).show();
        }
    }

    public void release() {
        if(audioRecord != null && isRecording){
            isRecording = false;
            audioRecord.stop();
            audioRecord.release();
            audioRecord = null;
        }
    }

    private class AudioRecordThread implements Runnable {
        @Override
        public void run() {
            writeDataToFile();//往文件中写入裸数据
            copyWaveFile(audioFile,waveFile);//给裸数据加上头文件
        }
    }

    private void copyWaveFile(String raw, String wav) {
        FileInputStream in;
        FileOutputStream out;
        long totalAudioLen;
        long totalDataLen;
        long longSampleRate = frequency;
        int channels = audioRecord.getChannelCount();
        Log.v("dddd","channel:" + channels);
        long byteRate = 16 * frequency * channels/8;
        byte[] data = new byte[bufferSizeBytes];
        try{
            in = new FileInputStream(raw);
            out = new FileOutputStream(wav);
            totalAudioLen = in.getChannel().size();
            totalDataLen = totalAudioLen + 36;

            WriteWaveFileHeader(out, totalAudioLen, totalDataLen, longSampleRate, channels, byteRate);
            while (in.read(data) != -1){
                out.write(data);
            }
            in.close();
            out.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    private void WriteWaveFileHeader(FileOutputStream out, long totalAudioLen, long totalDataLen, long longSampleRate, int channels, long byteRate) throws IOException {
        byte[] header = new byte[44];
        header[0] = 'R'; // RIFF/WAVE header
        header[1] = 'I';
        header[2] = 'F';
        header[3] = 'F';
        header[4] = (byte) (totalDataLen & 0xff);
        header[5] = (byte) ((totalDataLen >> 8) & 0xff);
        header[6] = (byte) ((totalDataLen >> 16) & 0xff);
        header[7] = (byte) ((totalDataLen >> 24) & 0xff);
        header[8] = 'W';
        header[9] = 'A';
        header[10] = 'V';
        header[11] = 'E';
        header[12] = 'f'; // 'fmt ' chunk
        header[13] = 'm';
        header[14] = 't';
        header[15] = ' ';
        header[16] = 16; // 4 bytes: size of 'fmt ' chunk
        header[17] = 0;
        header[18] = 0;
        header[19] = 0;
        header[20] = 1; // format = 1
        header[21] = 0;
        header[22] = (byte) channels;
        header[23] = 0;
        header[24] = (byte) (longSampleRate & 0xff);
        header[25] = (byte) ((longSampleRate >> 8) & 0xff);
        header[26] = (byte) ((longSampleRate >> 16) & 0xff);
        header[27] = (byte) ((longSampleRate >> 24) & 0xff);
        header[28] = (byte) (byteRate & 0xff);
        header[29] = (byte) ((byteRate >> 8) & 0xff);
        header[30] = (byte) ((byteRate >> 16) & 0xff);
        header[31] = (byte) ((byteRate >> 24) & 0xff);
        header[32] = (byte) (2 * 16 / 8); // block align
        header[33] = 0;
        header[34] = 16; // bits per sample
        header[35] = 0;
        header[36] = 'd';
        header[37] = 'a';
        header[38] = 't';
        header[39] = 'a';
        header[40] = (byte) (totalAudioLen & 0xff);
        header[41] = (byte) ((totalAudioLen >> 8) & 0xff);
        header[42] = (byte) ((totalAudioLen >> 16) & 0xff);
        header[43] = (byte) ((totalAudioLen >> 24) & 0xff);
        out.write(header, 0, 44);
    }

    private void writeDataToFile() {
        byte[] audioData = new byte[bufferSizeBytes];
        FileOutputStream fos = null;
        int readSize;

        try {
            File file = new File(audioFile);
            if(file.exists()){
                file.delete();
            }
            fos = new FileOutputStream(file);//建立可存取字节的文件
        }catch (Exception e){
            e.printStackTrace();
        }
        while(isRecording){
            readSize = audioRecord.read(audioData,0,bufferSizeBytes);
            if(AudioRecord.ERROR_INVALID_OPERATION != readSize){
                try{
//                    int t = 0;
//                    for(int i = 0;i <audioData.length;i++){
//                        volume += audioData[i] * audioData[i];
//                    }
//                    Log.v("dddd","test:" + (int) (Math.abs((int)(volume /(float)readSize)/10000) >> 1));

                    fos.write(audioData);
                }catch (IOException e){
                    e.printStackTrace();
                }
            }
        }
        try{
            fos.close();
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}
